﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace NullCommander
{
    public partial class frmFind : Form
    {
        public frmFind()
        {
            InitializeComponent();
        }

        private void frmFind_Load(object sender, EventArgs e)
        {
            edtFindDateCreate.CustomFormat = ClassHelpers.DATE_TIME_FORMAT;
            edtFindDateModification.CustomFormat = ClassHelpers.DATE_TIME_FORMAT;
        }

        /// <summary>
        /// Нахождение файлов и каталогов путем прямого сравнения заданных параметров поиска.
        /// </summary>
        /// <param name="path">Путь поиска.</param>
        /// <param name="name">Имя искомого файла/каталога. Чтобы игнорировать этот параметр необходимо name оставить пустым, либо присвоить значение "*".</param>
        /// <param name="size">Размер искомого файла. Чтобы игнорировать этот параметр необходимо передать size &lt; 0.</param>
        /// <param name="dateCreate">Дата создания искомого файла/каталога. Чтобы игнорировать этот параметр необходимо dateCreate передать равным DateTime.MinValue.</param>
        /// <param name="dateModification">Дата изменения искомого файла/каталога. Чтобы игнорировать этот параметр необходимо dateModification передать равным DateTime.MinValue.</param>
        /// <param name="subDir">Искать ли в подкаталогах.</param>
        /// <returns>Список путей найденных файлов/каталогов.</returns>
        private List<ShortFileInfo> FindFiles(String path, String name, Int64 size, DateTime dateCreate,
            DateTime dateModification, Boolean subDir)
        {
            // Список, который будет хранить пути найденных файлов и каталогов.
            var foundList = new List<ShortFileInfo>();
            try
            {
                // Очередь, содерщажая список каталогов.
                var queueDir = new Queue<DirectoryInfo>();
                // Опреляем параметры поиска.
                var noUseName = String.IsNullOrEmpty(name) || name == "*";
                var noUseSize = size < 0;
                var noUseDateCreate = dateCreate == DateTime.MinValue;
                var noUseDateModification = dateModification == DateTime.MinValue;
                // Получаем базовый каталог, в котором будем искать.
                var dirInfo = new DirectoryInfo(path);
                // Добавляем его в очередь.
                queueDir.Enqueue(dirInfo);
                do
                {
                    // Достаем очередной каталог и начинаем искать в нем файлы.
                    dirInfo = queueDir.Dequeue();
                    // Список подкаталогов получаем только в случае, если при поиске не был указан размер файла,
                    // либо поиск ведется с учетом подкаталогов.
                    if (noUseSize || subDir)
                    {
                        foreach (var dir in dirInfo.GetDirectories())
                        {
                            // Если поиск осуществляется с учетом подкаталогов, загружаем их в очередь.
                            if (subDir)
                                queueDir.Enqueue(dir);
                            // Смотрим, подходит ли данный каталог под условия поиска.
                            if ((noUseSize) &&
                                (noUseDateCreate || dateCreate == dir.CreationTime) &&
                                (noUseDateModification || dateModification == dir.LastWriteTime) &&
                                (noUseName || String.Compare(dir.Name, name) == 0))
                                foundList.Add((ShortFileInfo)dir);

                        }
                    }
                    // Получаем список файлов.
                    foreach (var file in dirInfo.GetFiles())
                        if ((noUseSize || size == file.Length) &&
                            (noUseDateCreate || dateCreate == file.CreationTime) &&
                            (noUseDateModification || dateModification == file.LastWriteTime) &&
                            (noUseName || String.Compare(file.Name, name) == 0))
                            foundList.Add((ShortFileInfo)file);
                } while (queueDir.Count > 0);
            }
            catch
            {
            }
            return foundList;
        }

        private void btnFind_Click(object sender, EventArgs e)
        {
            folderBrowserDialog.SelectedPath = edtFindPath.Text;
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
                edtFindPath.Text = folderBrowserDialog.SelectedPath;
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            // Очищаем результаты поиска.
            listView.Clear();
            Int64 size;
            // Ищем файлы,согласно заданным параметрам.
            var foundsList = FindFiles(edtFindPath.Text,
                cbxUseName.Checked ? edtFindName.Text : String.Empty,
                cbxUseSize.Checked && Int64.TryParse(edtFindSize.Text, out size) ? size : -1,
                cbxUseDateCreate.Checked ? edtFindDateCreate.Value : DateTime.MinValue,
                cbxUseDateModification.Checked ? edtFindDateModification.Value : DateTime.MinValue,
                cbxSubDir.Checked);
            // Результат поиска в статусбар.
            toolStripStatusLabel.Text = String.Format("Найдено элементов: {0}", listView.Items.Count);
            
            if (foundsList.Count == 0)
            {
                MessageBox.Show("Файлы не найдены.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            // Переносим результаты поиска в список найденных файлов.
            var items = new List<ListViewItem>(foundsList.Count);
            foreach (var info in foundsList)
            {
                var item = new ListViewItem(info.Path);
                item.SubItems.Add(info.IsDirectory ? "папка" : "файл");
                item.SubItems.Add(ClassHelpers.FileSizeToString(info.Size));
                item.SubItems.Add(info.DateCreate.ToString(ClassHelpers.DATE_TIME_FORMAT));
                item.SubItems.Add(info.DateModification.ToString(ClassHelpers.DATE_TIME_FORMAT));
                items.Add(item);
            }
            listView.Items.AddRange(items.ToArray());
        }

    }
}
